<!--表格中每个单元格的组件，文本输入框，下拉选择组件等-->
<template>
  <div
    v-show="editor.type&&editor.type!='hdmenu'"
    class="c-table-editor-box"
    :style="{top:editor.top,left:editor.left,width:editor.width,height:editor.height}"
  >
    <input
      ref="input"
      v-if="editor.type==='text'"
      v-focus
      type="text"
      class="c-table-editor-box-item"
      v-model="editor.row[editor.fieldName]"
      @input="tdChange"
    />

    <input
      ref="input"
      v-if="editor.type=='number'"
      v-focus
      type="text"
      class="c-table-editor-box-item"
      :value="editor.row[editor.fieldName]"
      @input="(e)=>editor.oninput(e,tdChange)"
    />

    <a-select
      v-if="editor.type=='select'"
      v-focus
      showArrow
      allowClear
      show-search
      class="c-table-editor-box-item"
      :dropdownMatchSelectWidth="editor.css?editor.css.dropdownMatchSelectWidth:false"
      :dropdownStyle="editor.css?editor.css.dropdownStyle:null"
      :mode="editor.mode"
      :value="editor.value"
      placeholder="请选择"
      :filter-option="filterOption"
      @change="editor.setVal"
      @search="selectEditorSearch"
      @popupScroll="(e)=>selectEditorScroll(e)"
    >
      <a-select-option
        v-for="item of getSelectEditorOptions()"
        :key="item[editor.dataValue]"
        :value="item[editor.dataValue]"
      >{{ item[editor.dataTitle]?item[editor.dataTitle]:' ' }}</a-select-option>
    </a-select>

    <a-tree-select
        v-if="editor.type=='treeSelect'"
        v-focus
        allowClear
        show-search
        :multiple="editor.multi"
        class="c-table-editor-box-item"
        v-model="editor.row[editor.fieldName]"
        :dropdownMatchSelectWidth="editor.css?editor.css.dropdownMatchSelectWidth:false"
        :dropdownStyle="editor.css?editor.css.dropdownStyle:null"
        :tree-data="editor.treeData"
        :dropdown-style="{ maxHeight: '200px', overflow: 'auto' }"
        :filterTreeNode="filterTreeNode"
        @change="editor.type=undefined"
    ></a-tree-select>


    <a-date-picker
      v-if="editor.type=='date'"
      v-focus
      class="c-table-editor-box-item"
      v-model="editor.date"
      :mode="editor.mode"
      :format="editor.format"
      @change="dateChange"
      @panelChange="panelChange"
    />

  </div>
</template>

<script>
import moment from 'moment'
import '../css/table.less'
export default {
  name: 'AntTableEditor',
  directives: {
    focus: {
      // 自动获取光标指令的定义
      inserted: function(el) {
        el.focus()
      }
    }
  },
  props: {
    // 编辑器
    editor: {
      type: Object,
      default: null
    },
    // 表格作用域
    tableThis: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      selectEditorLoadLimitNum: 20// 下拉编辑器单次渲染数据数
    }
  },
  mounted() {
    this.keyDown()
  },
  methods: {
    /**
     * 编辑框 失去焦点 隐藏
     */
    editItemBlur() {
      this.$emit('editItemBlur')
    },
    // 回车、TAB事件
    keyDown() {
      const _this = this
      const leftTableBody = this.tableThis.$refs.leftTableBody
      const rightTableBody = this.tableThis.$refs.rightTableBody
      const centerTableBody = this.tableThis.$refs.centerTableBody
      const func = function(rowIndex, colIndex, table) {
        let row
        // 创建双击触发事件
        const event = new Event('dblclick', {
          view: window,
          bubbles: true,
          cancelable: true
        })
        if (table === 'left') {
          row = leftTableBody.firstChild.lastChild.childNodes[rowIndex].childNodes[colIndex + 4]
        } else if (table === 'right') {
          row = rightTableBody.firstChild.lastChild.childNodes[rowIndex].childNodes[colIndex]
        } else {
          row = centerTableBody.firstChild.lastChild.childNodes[rowIndex].childNodes[colIndex]
        }
        // 自动调整滚动条位置
        _this.tableThis.autoScroll(row, table)
        setTimeout(() => {
          row.dispatchEvent(event)
        }, 100)
      }
      _this.$el.onkeydown = e => {
        if (e.repeat || !_this.editor.row || (e.code !== 'Tab' && e.code !== 'Enter' && e.code !== 'ArrowUp' && e.code !== 'ArrowDown')) {
          return
        }
        _this.editItemBlur()
        let colIndex
        let rowIndex = _this.tableThis.loadAllTableData.findIndex(el => el === this.editor.row)
        const titleArr = _this.tableThis.getTabTitleArr
        // Tab Enter 键 查找下一个编辑单元格位置，未找到就是下一行的当前位置
        if (e.code === 'Tab' || e.code === 'Enter') {
          e.preventDefault()
          const nextEditCell = titleArr.find((el, index) => index > titleArr.findIndex(item => item.field === this.editor.fieldName) && el.edit && el.type !== 'switch' && el.type !== 'checkBox')
          let table = nextEditCell ? nextEditCell.fixed : null
          if (nextEditCell) {
            // 当前行的下一个元素
            colIndex = titleArr.filter(el => table ? el.fixed === table : !el.fixed).findIndex(el => el.field === nextEditCell.field)
          } else if (rowIndex !== this.tableThis.loadAllTableData.length - 1) {
            rowIndex++
            _this.tableThis.setCurrentRow(this.tableThis.loadAllTableData[rowIndex])
            const firstEditCell = titleArr.find(el => el.edit && el.type !== 'checkBox' && el.type !== 'switch')
            colIndex = titleArr.filter(el => firstEditCell.fixed ? el.fixed === firstEditCell.fixed : !el.fixed).findIndex(el => el.field === firstEditCell.field)
            table = firstEditCell.fixed
          } else {
            return
          }
          func(rowIndex, colIndex, table)
        } else if (e.code === 'ArrowUp' || e.code === 'ArrowDown') { // 键盘 上、下 键切换
        e.preventDefault()
          if ((e.code === 'ArrowUp' && rowIndex === 0) || (e.code === 'ArrowDown' && rowIndex === (this.tableThis.loadAllTableData.length - 1))) {
            return
          }
          if (e.code === 'ArrowUp') {
            rowIndex--
          } else if (e.code === 'ArrowDown') {
            rowIndex++
          }
          colIndex = titleArr.filter(el => this.editor.fieldInfo.fixed ? el.fixed === this.editor.fieldInfo.fixed : !el.fixed).findIndex(el => el.field === this.editor.fieldInfo.field)
          func(rowIndex, colIndex, this.editor.fieldInfo.fixed)
        } else {
          _this.isKeyDownLoading = false
        }
      }
    },
    /**
     * 编辑输入框回调
     */
    tdChange() {
      this.$emit('tdChange', { fieldName: this.editor.fieldName, row: this.editor.row })
    },
    /**
     * 筛选下拉框
     * @param input
     * @param option
     * @returns {boolean}
     */
    filterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },
    /**
     * 筛选下拉树
     * @param value
     * @param treeNode
     * @returns {boolean}
     */
    filterTreeNode(value, treeNode) {
      return treeNode.data.props.title.indexOf(value) > -1
    },
    /**
     * 日期改变回调
     * @param date
     * @param dateString
     */
    dateChange(date, dateString) {
      this.editor.date = date
      this.editor.row[this.editor.fieldName] = dateString
      this.editItemBlur()
    },
    /**
     * 自定义日期面板回调
     * @param value
     */
    panelChange(value) {
      this.editor.date = value
      this.editor.row[this.editor.fieldName] = moment(value).format(this.editor.format)
      this.editItemBlur()
    },
    /**
     * 获取下拉编辑器加载得数据
     * @returns {*}
     */
    getSelectEditorOptions() {
      let list = this.editor.list
      const limitNum = (this.editor.selectDropdownLoadMore ? this.editor.selectDropdownLoadMore : 1) * this.selectEditorLoadLimitNum
      if (this.editor.searchText) {
        list = list.filter(el => el[this.editor.dataTitle].indexOf(this.editor.searchText) > -1)
      }
      const arr = list.filter((el, index) => index < limitNum)
      // 判断当前是否有选中数据，且选中数据在当前集合中，没有就找到该数据，添加到集合中
      if (this.editor.value) {
        const option = this.editor.list.find(el => el[this.editor.dataValue] === this.editor.value)
        if (option && !arr.find(el => el[this.editor.dataValue] === this.editor.value)) {
          arr.push(option)
        }
      }
      return arr
    },
    /**
     * 搜索下拉选项
     * @param value
     */
    selectEditorSearch(value) {
      this.editor.searchText = value
      this.$forceUpdate()
    },
    /**
     * 表格标题筛选数据数据集 滚动条滚动-动态加载数据
     * @param e
     */
    selectEditorScroll(e) {
      // 内容区域总高度
      const totalHeight = e.srcElement.firstChild.clientHeight * (this.editor.selectDropdownLoadMore ? this.editor.selectDropdownLoadMore : 1) * this.selectEditorLoadLimitNum
      // 内容区域可是高度
      const relativeHeight = e.srcElement.clientHeight
      // 滚动条 滚动距离
      const scrollTop = e.srcElement.scrollTop
      // 当滚动条滚动到底部距离 < 100 时，并且当前可视数据小于总数据时，动态加载可视数据
      if ((totalHeight - scrollTop - relativeHeight) < 100 && (this.editor.selectDropdownLoadMore ? this.editor.selectDropdownLoadMore : 1) * this.selectEditorLoadLimitNum < this.editor.list.length) {
        this.$set(this.editor, 'selectDropdownLoadMore', this.editor.selectDropdownLoadMore ? this.editor.selectDropdownLoadMore + 1 : 2)
        this.$forceUpdate()
      }
    }
  },
  watch: {
    'editor.type'(val) {
      if (val === 'text' || val === 'number') {
        this.$nextTick(() => {
          setTimeout(() => {
            if (this.$refs.input) {
              this.$refs.input.focus()
            }
          }, 300)
        })
      }
    }
  }
}
</script>
